Adding some more judges, here and there.
[and.git] / lib / Mi manual de algoritmos / version_world_finals_2009 / manual.tex
blob68f7dd6dbacff307d0209130e54927ead8f455d3
1 \documentclass[10pt,letterpaper,twocolumn,twosided]{article}
2 %\documentclass[10pt,letterpaper]{article}
3 % ---------------------------------------------------------------
4 \usepackage[utf8]{inputenc}
5 \usepackage[spanish]{babel}
6 \usepackage{listings}
7 \usepackage[usenames,dvipsnames]{color}
8 \usepackage{amsmath}
9 \usepackage{verbatim}
10 \usepackage{hyperref}
11 \usepackage{color}
12 \usepackage{geometry}
13 %Poner la página en landscape
14 \geometry{verbose,landscape,letterpaper,tmargin=2cm,bmargin=2cm,lmargin=2cm,rmargin=2cm}
16 \newcommand{\codigofuente}[1]{
17 \verbatiminput{#1}
18 \dotfill
20 \setlength{\columnsep}{0.25in}
21 \setlength{\columnseprule}{1px}
23 % ---------------------------------------------------------------
24 \begin{document}
25 % ---------------------------------------------------------------
26 \title{Resumen de algoritmos para torneos de programación}
27 \author{Andrés Mejía}
28 \date{\today}
29 \maketitle
30 % ---------------------------------------------------------------
32 % ---------------------------------------------------------------
33 \tableofcontents
34 % \lstlistoflistings
35 \lstloadlanguages{C++}
36 % ---------------------------------------------------------------
37 \section{Plantilla}
38 \codigofuente{./src/template.cpp}
39 % ---------------------------------------------------------------
40 \section{Teoría de números}
41 % ---------------------------------------------------------------
42 \subsection{Big mod}
43 %\input{./src/number_theory/bigmod}%.tex
44 \codigofuente{./src/number_theory/bigmod.cpp}
46 \subsection{Criba de Eratóstenes}
47 \small
48 \textbf{Field-testing:}
49 \begin{itemize}
50 \item \emph{SPOJ} - 2912 - Super Primes
51 \item \emph{Live Archive} - 3639 - Prime Path
52 \end{itemize}
54 \normalsize
55 Marca los números primos en un arreglo. Algunos tiempos de ejecución:
56 \begin{center}
57 \begin{tabular}{c c}
58 \hline\hline
59 SIZE & Tiempo (s) \\ [0.5ex]
60 \hline
61 100000 & 0.003 \\
62 1000000 & 0.060 \\
63 10000000 & 0.620 \\
64 100000000 & 7.650 \\ [1ex]
65 \hline
66 \end{tabular}
67 \end{center}
68 \codigofuente{./src/number_theory/criba.cpp}
70 \subsection{Divisores de un número}
71 Imprime todos los divisores de un número (en desorden) en O($\sqrt{n}$).
72 Hasta 4294967295 (máximo \textit{unsigned int}) responde instantáneamente. Se puede
73 forzar un poco más usando \textit{unsigned long long} pero más allá de $10^{12}$ empieza a
74 responder muy lento.
75 \codigofuente{./src/number_theory/divisores.cpp}
77 \section{Combinatoria}
78 \subsection{Cuadro resumen}
79 Fórmulas para combinaciones y permutaciones:
80 \begin{center}
81 \renewcommand{\arraystretch}{2} %Multiplica la altura de cada fila de la tabla por 2
82 % Si quiero aumentar el tamaño de una fila en particular insertar \rule{0cm}{1cm} en esa fila.
83 \begin{tabular}{| c | c | c |}
84 \hline
85 \textit{Tipo} & \textit{¿Se permite la repetición?} & \textit{Fórmula} \\ [1.5ex]
86 \hline\hline
88 $r$-permutaciones & No & $ \displaystyle\frac{n!}{(n-r)!} $ \\ [1.5ex]
89 \hline
90 $r$-combinaciones & No & $ \displaystyle\frac{n!}{r!(n-r)!} $ \\ [1.5ex]
91 \hline
92 $r$-permutaciones & Sí & $ \displaystyle n^{r} $ \\
93 \hline
94 $r$-combinaciones & Sí & $ \displaystyle\frac{(n+r-1)!}{r!(n-1)!} $ \\ [1.5ex]
95 \hline
96 \end{tabular}
97 \renewcommand{\arraystretch}{1}
98 \end{center}
99 Tomado de \textit{Matemática discreta y sus aplicaciones}, Kenneth Rosen, 5${}^{\hbox{ta}}$ edición, McGraw-Hill, página 315.
101 \subsection{Combinaciones, coeficientes binomiales, triángulo de Pascal}
102 \emph{Complejidad:} $ O(n^2) $ \\
103 $$ {n \choose k} = \left\{
104 \begin{array}{c l}
105 1 & k = 0\\
106 1 & n = k\\
107 \displaystyle {n - 1 \choose k - 1} + {n - 1 \choose k} & \mbox{en otro caso}\\
108 \end{array}
109 \right.
112 \codigofuente{./src/combinatoria/pascal_triangle.cpp}
114 \bigskip
115 \textbf{Nota:} $ \displaystyle {n \choose k } $ está indefinido en el código anterior si $ n > k$. ¡La tabla puede estar llena con cualquier basura del compilador!
117 \subsection{Permutaciones con elementos indistinguibles}
118 El número de permutaciones \underline{diferentes} de $n$ objetos, donde hay $n_{1}$ objetos indistinguibles de tipo 1,
119 $n_{2}$ objetos indistinguibles de tipo 2, ..., y $n_{k}$ objetos indistinguibles de tipo $k$, es
121 \frac{n!}{n_{1}!n_{2}! \cdots n_{k}!}
123 \textbf{Ejemplo:} Con las letras de la palabra \texttt{PROGRAMAR} se pueden formar $ \displaystyle \frac{9!}{2! \cdot 3!} =
124 30240 $ permutaciones \underline{diferentes}.
125 \subsection{Desordenes, desarreglos o permutaciones completas}
127 Un desarreglo es una permutación donde ningún elemento $i$ está en la
128 posición $i$-ésima. Por ejemplo, \textit{4213} es un desarreglo de 4 elementos pero
129 \textit{3241} no lo es porque el 2 aparece en la posición 2.
131 Sea $D_{n}$ el número de desarreglos de $n$ elementos, entonces:
132 $$ {D_{n}} = \left\{
133 \begin{array}{c l}
134 1 & n = 0\\
135 0 & n = 1\\
136 (n-1)(D_{n-1} + D_{n-2}) & n \geq 2\\
137 \end{array}
138 \right.
140 Usando el principio de inclusión-exclusión, también se puede encontrar la fórmula
142 D_{n} = n!\left [ 1 - \frac{1}{1!} + \frac{1}{2!} - \frac{1}{3!} + \cdots + (-1)^{n}\frac{1}{n!} \right ]
143 = n! \sum_{i=0}^{n} \frac{(-1)^{i}}{i!}
146 \section{Grafos}
147 \subsection{Algoritmo de Dijkstra}
148 El peso de todas las aristas debe ser no negativo.
150 \codigofuente{./src/grafos/dijkstra.cpp}
152 \subsection{Minimum spanning tree: Algoritmo de Prim}
154 \codigofuente{./src/grafos/prim.cpp}
156 \subsection{Minimum spanning tree: Algoritmo de Kruskal + Union-Find}
157 \codigofuente{./src/grafos/kruskal.cpp}
159 \subsection{Algoritmo de Floyd-Warshall}
160 \codigofuente{./src/grafos/floyd.cpp}
162 \subsection{Algoritmo de Bellman-Ford}
163 Si no hay ciclos de coste negativo, encuentra la distancia más corta
164 entre un nodo y todos los demás. Si sí hay, permite saberlo. \\ El
165 coste de las aristas \underline{} puede ser negativo
166 (\emph{Debería}, si no es así se puede usar Dijsktra o Floyd).
167 \codigofuente{./src/grafos/bellman.cpp}
169 \subsection{Puntos de articulación}
170 \codigofuente{./src/grafos/puntos_articulacion.cpp}
172 \subsection{Máximo flujo: Método de Ford-Fulkerson, algoritmo de Edmonds-Karp}
173 El algoritmo de Edmonds-Karp es una modificación al método de Ford-Fulkerson. Este último
174 utiliza DFS para hallar un camino de aumentación, pero la sugerencia de Edmonds-Karp
175 es utilizar BFS que lo hace más eficiente en algunos grafos.
176 \medskip
178 \codigofuente{./src/grafos/ford_fulkerson.cpp}
180 \subsection{Máximo flujo para grafos dispersos usando Ford-Fulkerson}
181 \codigofuente{./src/grafos/ford_fulkerson_sparse.cpp}
183 \subsection{Máximo flujo para grafos disperos usando algoritmo de Dinic}
184 \codigofuente{./src/grafos/dinic.cpp}
186 \subsection{Máximo flujo mínimo costo}
187 Implementación de Misof:
188 \codigofuente{./src/grafos/mincostmaxflow.cpp}
190 \subsection{Componentes fuertemente conexas: Algoritmo de Tarjan}
191 \label{tarjan}
192 \codigofuente{./src/grafos/tarjan.cpp}
194 \subsection{2-Satisfiability}
195 Dada una ecuación lógica de conjunciones de disyunciones de 2 términos, se pretente decidir si existen valores de verdad que puedan asignarse a las variables para hacer cierta la ecuación. \\
196 Por ejemplo, $(b_1 \vee \neg b_2) \wedge (b_2 \vee b_3) \wedge (\neg b_1 \vee \neg b_2) $ es verdadero cuando $b_1$ y $b_3$ son verdaderos y $b_2$ es falso. \\
197 \textbf{Solución:} Se sabe que $(p \rightarrow q) \leftrightarrow (\neg p \vee q)$. Entonces se traduce cada disyunción en una implicación y se crea un grafo donde los nodos son cada variable y su negación. Cada implicación es una arista en este grafo. Existe solución si nunca se cumple que una variable y su negación están en la misma componenete fuertemente conexa (Se usa el algoritmo de Tarjan, \ref{tarjan}).
199 \section{Programación dinámica}
200 \subsection{Longest common subsequence}
201 \codigofuente{./src/dp/lcs.cpp}
202 \subsection{Partición de troncos}
203 Este problema es similar al problema de \textit{Matrix Chain Multiplication}. Se tiene
204 un tronco de longitud $n$, y $m$ puntos de corte en el tronco. Se puede hacer un corte a la vez,
205 cuyo costo es igual a la longitud del tronco. ¿Cuál es el mínimo costo para partir todo el tronco
206 en pedacitos individuales?
208 \medskip
209 \textbf{Ejemplo:} Se tiene un tronco de longitud 10. Los puntos de corte son 2, 4, y 7. El mínimo
210 costo para partirlo es 20, y se obtiene así:
211 \begin{itemize}
212 \item Partir el tronco (0, 10) por 4. Vale 10 y quedan los troncos (0, 4) y (4, 10).
213 \item Partir el tronco (0, 4) por 2. Vale 4 y quedan los troncos (0, 2), (2, 4) y (4, 10).
214 \item No hay que partir el tronco (0, 2).
215 \item No hay que partir el tronco (2, 4).
216 \item Partir el tronco (4, 10) por 7. Vale 6 y quedan los troncos (4, 7) y (7, 10).
217 \item No hay que partir el tronco (4, 7).
218 \item No hay que partir el tronco (7, 10).
219 \item El costo total es $10+4+6 = 20$.
220 \end{itemize}
222 \medskip
223 El algoritmo es $O(n^3)$, pero optimizable a $O(n^2)$ con una tabla adicional:
224 \codigofuente{./src/dp/particion_troncos.cpp}
226 \section{Geometría}
227 \subsection{Área de un polígono}
228 Si P es un polígono simple (no se intersecta a sí mismo) su área está dada por: \\
230 $ A(P) = \frac{1}{2} \displaystyle\sum_{i=0}^{n-1} (x_{i} \cdot y_{i+1} - x_{i+1} \cdot y_{i}) $ \\
231 \bigskip
232 \codigofuente{./src/geometria/polygon_area.cpp}
234 \subsection{Centro de masa de un polígono}
235 Si P es un polígono simple (no se intersecta a sí mismo) su centro de masa está dado por: \\
237 $ \displaystyle\bar{C}_{x} = \frac{ \displaystyle\iint_{R} x \, dA }{M} = \frac{1}{6M}\sum_{i=1}^{n} (y_{i+1} - y_{i}) (x_{i+1}^2 + x_{i+1} \cdot x_{i} + x_{i}^2) $
239 \medskip
241 $\displaystyle\bar{C}_{y} = \frac{ \displaystyle\iint_{R} y \, dA }{M} = \frac{1}{6M} \sum_{i=1}^{n} (x_{i} - x_{i+1}) (y_{i+1}^2 + y_{i+1} \cdot y_{i} + y_{i}^2)$
243 \medskip
245 Donde $ M $ es el área del polígono. \\
247 Otra posible fórmula equivalente:
249 $ \displaystyle\bar{C}_{x} = \frac{1}{6A} \sum_{i=0}^{n-1} (x_{i} + x_{i+1}) (x_{i} \cdot y_{i+1} - x_{i+1} \cdot y_{i}) $
251 \medskip
253 $ \displaystyle\bar{C}_{y} = \frac{1}{6A} \sum_{i=0}^{n-1} (y_{i} + y_{i+1}) (x_{i} \cdot y_{i+1} - x_{i+1} \cdot y_{i}) $
256 \subsection{Convex hull: Graham Scan}
257 \emph{Complejidad:} $ O(n \log_{2}{n}) $
258 \codigofuente{./src/geometria/grahamscan.cpp}
260 \subsection{Convex hull: Andrew's monotone chain}
261 \emph{Complejidad:} $ O(n \log_{2}{n}) $
262 \codigofuente{./src/geometria/monotonechain.cpp}
264 \subsection{Mínima distancia entre un punto y un segmento}
265 \codigofuente{./src/geometria/distance_point_to_segment.cpp}
267 \subsection{Mínima distancia entre un punto y una recta}
268 \codigofuente{./src/geometria/distance_point_to_line.cpp}
270 \subsection{Determinar si un polígono es convexo}
271 \codigofuente{./src/geometria/is_convex_polygon.cpp}
273 \subsection{Determinar si un punto está dentro de un polígono convexo}
274 \codigofuente{./src/geometria/is_inside_convex_polygon.cpp}
276 \subsection{Determinar si un punto está dentro de un polígono cualquiera}
277 \small
278 \textbf{Field-testing:}
279 \begin{itemize}
280 \item \emph{TopCoder} - SRM 187 - Division 2 Hard - PointInPolygon
281 \end{itemize}
282 \codigofuente{./src/geometria/is_inside_concave_polygon.cpp}
284 \subsection{Intersección de dos rectas}
285 \codigofuente{./src/geometria/line_line_intersection.cpp}
287 \subsection{Intersección de dos segmentos de recta}
288 \codigofuente{./src/geometria/segment_segment_intersection.cpp}
289 % ---------------------------------------------------------------
290 \section{Estructuras de datos}
291 \subsection{Árboles de Fenwick ó Binary indexed trees}
293 Se tiene un arreglo $\{a_0, a_1, \cdots, a_{n-1}\}$. Los árboles
294 de Fenwick permiten encontrar $ \displaystyle \sum_{k=i}^{j} a_k $ en orden $O(\log_{2}{n})$ para parejas de $(i, j)$ con $i \leq j$. De la misma manera, permiten sumarle una cantidad a un $a_i$ también en tiempo $O(log_{2}{n})$.
295 \medskip
296 \codigofuente{./src/estructuras/fenwick.cpp}
298 \subsection{Segment tree}
299 \codigofuente{./src/estructuras/segment_tree.cpp}
301 % ---------------------------------------------------------------
302 \section{Misceláneo}
303 \subsection{El \textit{parser} más rápido del mundo}
304 \begin{itemize}
305 \item Cada no-terminal: un método
306 \item Cada lado derecho:
307 \begin{itemize}
308 \item invocar los métodos de los no-terminales o
309 \item Cada terminal: invocar proceso \textit{match}
310 \end{itemize}
311 \item Alternativas en una producción: se hace un \textit{if}
312 \end{itemize}
313 \medskip
314 No funciona con gramáticas recursivas por izquierda ó en las que en algún momento haya
315 varias posibles escogencias que empiezan por el mismo caracter (En ambos casos la gramática se puede factorizar).
317 \medskip
318 \textbf{Ejemplo:} Para la gramática:
320 A \longrightarrow (A)A
321 $$ $$
322 A \longrightarrow \epsilon
325 \codigofuente{./src/misc/parser_recursivo_desc.cpp}
327 \subsection{Checklist para corregir un Wrong Answer}
328 Consideraciones que podrían ser causa de un Wrong Answer:
329 \begin{itemize}
330 \begin{item}
331 Overflow.
332 \end{item}
334 \begin{item}
335 El programa termina anticipadamente por la condición en el ciclo de lectura.
336 Por ejemplo, se tiene \verb_while (cin >> n >> k && n && k)_ y un caso válido de entrada
337 es n = 1 y k = 0.
338 \end{item}
340 \begin{item}
341 El grafo no es conexo.
342 \end{item}
344 \begin{item}
345 Puede haber varias aristas entre el mismo par de nodos.
346 \end{item}
348 \begin{item}
349 Las aristas pueden tener costos negativos.
350 \end{item}
352 \begin{item}
353 El grafo tiene un sólo nodo.
354 \end{item}
356 \begin{item}
357 La cadena puede ser vacía.
358 \end{item}
360 \begin{item}
361 Las líneas pueden tener espacios en blanco al principio o al final (Cuidado al usar \texttt{getline} o \texttt{fgets}).
362 \end{item}
364 \begin{item}
365 El arreglo no se limpia entre caso y caso.
366 \end{item}
368 \begin{item}
369 Estás imprimiendo una línea en blanco con un espacio (\verb_printf(" \n")_ en vez de \verb_printf("\n")_ ó \verb_puts(" ")_ en vez de \verb_puts("")_).
370 \end{item}
372 \begin{item}
373 La rana se puede quedar quieta.
374 \end{item}
377 \end{itemize}
380 \section{Java}
381 \subsection{Entrada desde entrada estándar}
382 Este primer método es muy fácil pero es mucho más ineficiente porque utiliza Scanner en vez de BufferedReader:
383 \codigofuente{./src/java/io_estandar_easy.java}
385 \bigskip
387 Este segundo es más rápido:
388 \codigofuente{./src/java/io_estandar.java}
389 \subsection{Entrada desde archivo}
390 \codigofuente{./src/java/io_file.java}
392 \subsection{Mapas y sets}
393 Programa de ejemplo:
394 \codigofuente{./src/java/maps_sets.java} \\
395 La salida de este programa es: \\
396 \bigskip
397 \ttfamily
398 \fbox{\parbox{2.0in}{
399 Maps\\
400 m.size() = 1\\
401 465\\
402 null\\
404 Sets\\
405 54 presente.\\
406 s.size() = 3\\
407 54\\
408 3576\\
409 1000000007\\
410 s.size() = 0\\
413 \\ \normalfont\normalsize
414 \bigskip
416 Si quiere usarse una clase propia como llave del mapa o como elemento del set, la clase debe implementar
417 algunos métodos especiales: Si va a usarse un TreeMap ó TreeSet hay que implementar los métodos \texttt{compareTo} y
418 \texttt{equals} de la interfaz \texttt{Comparable} como en la sección \ref{colas_de_prioridad_java}. Si va a usarse
419 un HashMap ó HashSet hay más complicaciones.\\
420 \smallskip
421 \textbf{Sugerencia:} Inventar una manera de codificar y decodificar la clase en una String o un Integer y meter esa representación en el mapa o set: esas clases ya tienen los métodos implementados.
423 \subsection{Colas de prioridad}
424 \label{colas_de_prioridad_java}
425 Hay que implementar unos métodos. Veamos un ejemplo: \\
426 \codigofuente{./src/java/priority_queue.java}\\
427 La salida de este programa es: \\
429 \ttfamily
430 \fbox{\parbox{2.0in}{
431 peso = 0, destino = 12\\
432 peso = 0, destino = 8\\
433 peso = 0, destino = 13\\
434 peso = 3, destino = 7\\
435 peso = 1876, destino = 4\\
438 \normalfont\normalsize
440 Vemos que la función de comparación que definimos no tiene en cuenta \texttt{destino},
441 por eso no desempata cuando dos \texttt{Items} tienen el mismo \texttt{peso} si no que escoge
442 cualquiera de manera arbitraria.
444 \section{C++}
445 \subsection{Entrada desde archivo}
446 \codigofuente{./src/c++/io_file.cpp}
448 \subsection{Strings con caractéres especiales}
449 \codigofuente{./src/c++/unicode.cpp}
451 \emph{Nota}: Como alternativa a la función getline, se pueden utilizar las funciones fgetws y fputws, y más adelante swscanf y wprintf:
452 \codigofuente{./src/c++/fgetws.cpp}
454 \end{document}